package cn.netswap.crate.util;

import cn.netswap.crate.annotation.Table;
import cn.netswap.crate.exception.CrateDbTableEmptyException;
import com.google.common.base.CaseFormat;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;


import java.lang.reflect.Field;
import java.util.*;

public class AutoCrateTableSqlUtil {

    static Logger logger = LoggerFactory.getLogger(AutoCrateTableSqlUtil.class.getName());

    public static Map<String, String> property2SqlColumnMap = new HashMap<>();


    /**
     * 字段映射
     */
    static {
        property2SqlColumnMap.put("integer", "INT");
        property2SqlColumnMap.put("short", "INT");
        property2SqlColumnMap.put("long", "BIGINT");
        property2SqlColumnMap.put("bigdecimal", "INT");
        property2SqlColumnMap.put("double", "double precision");
        property2SqlColumnMap.put("float", "INT");
        property2SqlColumnMap.put("timestamp", "TIMESTAMP WITH TIME ZONE");
        property2SqlColumnMap.put("date", "TIMESTAMP WITH TIME ZONE");
        property2SqlColumnMap.put("string", "STRING");
        property2SqlColumnMap.put("mediumtext", "STRING");
    }

    /**
     * 自动生成表
     * @param clazz
     * @return
     * @throws CrateDbTableEmptyException
     */
    public static String generateTableSql(Class clazz) throws CrateDbTableEmptyException {
        Table table = AnnotationUtils.findAnnotation(clazz, Table.class);
        List<Field> fieldList = new ArrayList<>();
        String tableName = "";
        if(StringUtils.isBlank(table.name())){
            throw new CrateDbTableEmptyException(" CrateDb table must not null");
        }
        tableName = AutoCrateTableSqlUtil.upperToCamel(table.name());
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        StringBuffer column = new StringBuffer();
        for (int i = 0; i < fields.length; i++) {
            if (i == fields.length - 1) {
                column.append(getColumnSql(fields[i]).replace(",", ""));
            } else {
                column.append(getColumnSql(fields[i]));
            }
        }
        StringBuffer sql = new StringBuffer();
        sql.append("\n CREATE TABLE IF NOT EXISTS ; " + tableName + "  (").append(column).append(" \n ) ");
        logger.info(sql.toString());
        return sql.toString();

    }

    /**
     * 组装字段条件
     *
     * @param field
     * @return
     */
    private static String getColumnSql(Field field) {
        String tpl = "\n %s %s DEFAULT NULL,";
        String typeName = field.getType().getSimpleName().toLowerCase();
        String sqlType = property2SqlColumnMap.get(typeName);
        if (sqlType == null || sqlType.isEmpty()) {
            logger.info(field.getName() + ":" + field.getType().getName() + " 需要单独创建表");
            return "";
        }
        String column = upperToCamel(field.getName()).toUpperCase();
        String sql = String.format(tpl, column, sqlType.toUpperCase());
        return sql;
    }

    /**
     * 大写转驼峰
     * @param name
     * @return
     */
    private static String upperToCamel(String name){
        String lower = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE,name).toUpperCase();
        return lower;
    }

    /**
     * 驼峰转大写
     * @param name
     * @return
     */
    private static String CamelToUpper(String name){
        String upper =  CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name).toUpperCase();
        return upper;
    }



}
